﻿// This file is part of Code4Public (http://code4public.codeplex.com)
// Copyright 2011 Sina Iravanian - <sina@sinairv.com>
//
// This source file(s) may be redistributed, altered and customized
// by any means PROVIDING the authors name and all copyright
// notices remain intact.
// THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED. USE IT AT YOUR OWN RISK. THE AUTHOR ACCEPTS NO
// LIABILITY FOR ANY DATA DAMAGE/LOSS THAT THIS PRODUCT MAY CAUSE.
// ------------------------------------------------------------------

using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using Code4Public.Utils;
using Code4Public.Parsing;
using Code4Public.Settings;
using System.Diagnostics;

namespace Code4Public
{
    /// <summary>
    /// The Logic Core of the application
    /// </summary>
    public class Core
    {
        /// <summary>
        /// Gets or sets the reference to the collection of languages.
        /// </summary>
        public Languages.Languages Languages  { get; private set; }

        /// <summary>
        /// Gets or sets the reference to the collection of color profiles.
        /// </summary>
        public ColorProfilesCollection ColorProfiles  { get; private set; }

        /// <summary>
        /// Gets or sets the reference to the collection of themes.
        /// </summary>
        public ThemesCollection Themes { get; private set; }

        /// <summary>
        /// A dictionary of color-group names to their order number in the RTF color table
        /// </summary>
        private readonly Dictionary<string, int> m_dicGroupNameToOrder = new Dictionary<string, int>();

        /// <summary>
        /// Initializes a new instance of the <see cref="Core"/> class. Checks the 
        /// possible errors encountered during parsing the application settings.
        /// Also initializes and creates languages, color-profiles, and themes collections
        /// from their xml files, and shows possible errors encountered.
        /// </summary>
        public Core()
        {
            if (AppSettings.Settings.HasErrors)
            {
                MessageBox.Show(AppSettings.Settings.ParsingErrors.ToString());
            }

            Languages = new Languages.Languages(AppSettings.Settings.LanguagesFilePath);
            if (Languages.HasErrors)
            {
                MessageBox.Show(Languages.ParsingErrors.ToString());
            }

            ColorProfiles = new ColorProfilesCollection(AppSettings.Settings.ColorProfilesPath);
            if (ColorProfiles.HasErrors)
            {
                MessageBox.Show(ColorProfiles.ParsingErrors.ToString());
            }

            Themes = new ThemesCollection(AppSettings.Settings.ThemesPath);
            if (Themes.HasErrors)
            {
                MessageBox.Show(Themes.ParsingErrors.ToString());
            }
        }

        /// <summary>
        /// Creates the rtf colors table and fills the dicGroupNameToOrder dictionary.
        /// </summary>
        private string CreateColorsTable()
        {
            m_dicGroupNameToOrder.Clear();
            var sbRtfColorTable = new StringBuilder();
            sbRtfColorTable.Append(@"{\colortbl ;");

            // first add the system-wide default color
            m_dicGroupNameToOrder.Add("", 1);
            sbRtfColorTable.AppendFormat("{0};", ColorUtils.ColorToRtfTableEntry(AppSettings.Settings.DefaultTextColor));

            if (this.ColorProfiles.SelectedProfile != null)
            {
                int i = 2;

                foreach (var pair in this.ColorProfiles.SelectedProfile.GroupColors)
                {
                    sbRtfColorTable.AppendFormat("{0};", ColorUtils.ColorToRtfTableEntry(pair.Value.Color));
                    m_dicGroupNameToOrder.Add(pair.Key, i);
                    i++;
                }
            }

            sbRtfColorTable.Append("}");

            return sbRtfColorTable.ToString();
        }

        /// <summary>
        /// Gets the RTF color table.
        /// </summary>
        public string GetRtfColorTable()
        {
            return CreateColorsTable();
        }

        /// <summary>
        /// Gets the index of the color in the RTF table.
        /// </summary>
        /// <param name="expressionType">Type of the expression.</param>
        /// <param name="groupName">Name of the group that the expression belongs to. 
        /// This name is specified in the language definition.</param>
        public int GetColorIndex(ExpressionType expressionType, string groupName)
        {
            // the real group name in the color profiles
            string sysGroupName = "";
            switch (expressionType)
            {
                case ExpressionType.Whitespace:
                case ExpressionType.Newline:
                case ExpressionType.Identifier:
                    sysGroupName = CodeConstants.ColorProfile.GroupNameDefault;
                    break;
                case ExpressionType.Operator:
                    sysGroupName = CodeConstants.ColorProfile.GroupNameOperators;
                    break;
                case ExpressionType.Number:
                    sysGroupName = CodeConstants.ColorProfile.GroupNameNumbers;
                    break;
                case ExpressionType.Keyword:
                    sysGroupName = CodeConstants.ColorProfile.GroupNameKeywords;
                    break;
                case ExpressionType.Comment:
                    sysGroupName = CodeConstants.ColorProfile.GroupNameComments;
                    break;
                case ExpressionType.CommentLine:
                    sysGroupName = CodeConstants.ColorProfile.GroupNameCommentLines;
                    break;
                case ExpressionType.String:
                    sysGroupName = CodeConstants.ColorProfile.GroupNameStrings;
                    break;
                case ExpressionType.DelimitedGroup:
                case ExpressionType.WordGroup:
                    sysGroupName = groupName;
                    break;
                default:
                    Debug.Assert(false);
                    break;
            }

            int order;
            if (!m_dicGroupNameToOrder.TryGetValue(sysGroupName, out order))
            {
                if (!m_dicGroupNameToOrder.TryGetValue(CodeConstants.ColorProfile.GroupNameDefault, out order))
                {
                    order = 1;
                }
            }

            return order;
        }

        /// <summary>
        /// Maps the expression to the name of the color profile group. The expressions are defined
        /// by languages, the color profile group name is specified by color profiles. 
        /// </summary>
        /// <param name="ex">The expression.</param>
        public static string MapExpressionToColorProfileGroupName(Expression ex)
        {
            string grpName = "";
            switch (ex.Type)
            {
                case ExpressionType.Whitespace:
                case ExpressionType.Newline:
                case ExpressionType.Identifier:
                    grpName = CodeConstants.ColorProfile.GroupNameDefault;
                    break;
                case ExpressionType.Operator:
                    grpName = CodeConstants.ColorProfile.GroupNameOperators;
                    break;
                case ExpressionType.Number:
                    grpName = CodeConstants.ColorProfile.GroupNameNumbers;
                    break;
                case ExpressionType.Keyword:
                    grpName = CodeConstants.ColorProfile.GroupNameKeywords;
                    break;
                case ExpressionType.Comment:
                    grpName = CodeConstants.ColorProfile.GroupNameComments;
                    break;
                case ExpressionType.CommentLine:
                    grpName = CodeConstants.ColorProfile.GroupNameCommentLines;
                    break;
                case ExpressionType.String:
                    grpName = CodeConstants.ColorProfile.GroupNameStrings;
                    break;
                case ExpressionType.DelimitedGroup:
                case ExpressionType.WordGroup:
                    grpName = ex.Group;
                    break;
                default:
                    Debug.Assert(false);
                    break;
            }

            return grpName;
        }

    }
}
